package midend;

import antrl.SysYBaseVisitor;
import antrl.SysYParser;
import config.Config;
import midend.IR_Optimizer.*;
import midend.IR_Type.*;
import midend.IR_Value.*;
import org.antlr.v4.runtime.tree.TerminalNode;

import midend.IR_Instruction.*;

import java.util.*;

import static midend.IR_Builder.*;
import static midend.IR_Builder.Alloc;
import static midend.IR_Type.IR_Const.*;

public class IR_Visitor extends SysYBaseVisitor<IR_Value> {
    Scope currentScope = new Scope(null,"globalScope",  null);
    private IR_Module module;
    private IR_Builder builder;
    private IR_Type i32Type;
    private IR_Type i1Type;
    private IR_Type floatType;
    private IR_Type voidType;
    private IR_Value i32zero;
    private IR_Value floatZero;
    private Map<String, Integer> ConstIntVarMap;
    private Map<String, Float> ConstFloatVarMap;
    private IR_FuncBlock currentFunction = null;
    private IR_BaseBlock currentBlock = null;
    private String currentBlockName = null;
    private int localScopeCounter;
    private boolean arrayAddr;
    private List<IR_Value> ArrayList = new ArrayList<>();
    private List<Integer> dimension = new ArrayList<>();
    int curdimension;
    private boolean iscontinue = false;
    private boolean isbreak = false;

    private IR_BaseBlock trueblock;
    private IR_BaseBlock falseblock;

    public IR_Visitor(String source) {
        //创建module
        //截取最后一个/后的字符串作为module的名字
        String[] temp = source.split("/");
        String[] temp2 = temp[temp.length - 1].split("\\.");
        this.module = new IR_Module(temp2[0]);
        //初始化IRBuilder，后续将使用这个builder去生成IR IR
        this.builder = new IR_Builder();
        //初始化基本类型
        this.i32Type = IR_Int32.IR_Int32();
        this.i1Type = IR_Int1.IR_Int1();
        this.floatType = IR_Float.IR_Float();
        this.voidType = IR_Void.IR_Void();
        this.i32zero = new IR_Int_Value(0, i32Type);
        this.floatZero = new IR_Float_Value(0.0f);
        this.ConstIntVarMap = new LinkedHashMap<>();
        this.ConstFloatVarMap = new LinkedHashMap<>();
        this.arrayAddr = false;
        this.localScopeCounter = 0;
    }

    // 调用优化器进行优化
    public void optimize_Module() {
        New_Mem_To_Reg memToReg = new New_Mem_To_Reg(module);
        memToReg.run();
        module.constantPropagationForGlobalVars();
        Optimizer_Factory optimizerFactory = new Optimizer_Factory(module);
        for (IR_FuncBlock function : this.module.getFuncBlocks()) {
            optimizerFactory.optimize(function);
        }
        this.module.buildCFG();
        this.module.deleteInaccessibleBB();
        GVN gvn = new GVN(this.module);
        gvn.Optimize();
        Optimizer_Factory optimizerFactory2 = new Optimizer_Factory(module,Arrays.asList(new GCSE_Optimizer()));
        for (IR_FuncBlock function : this.module.getFuncBlocks()) {
            optimizerFactory2.optimize(function);
        }
        DeadCode_Eli DCE = new DeadCode_Eli(this.module);
        DCE.Optimize();
        if(Config.is_O1) {
            //循环不变式提取
            OptimizationManager licm = new OptimizationManager(this.module);
            licm.optimizeModule();

            //循环展开
            LoopUnroll loopUnroll = new LoopUnroll(this.module);
            loopUnroll.Optimize();
            //函数内联
            Func_Inline funcInline = new Func_Inline(this.module);
            funcInline.Optimize();
            GVN gvn2 = new GVN(this.module);
            gvn2.Optimize();
            DeadCode_Eli DCE2 = new DeadCode_Eli(this.module);
            DCE2.Optimize();

        }
        Useless_Load_Eli uselessLoadEli = new Useless_Load_Eli(module);
        uselessLoadEli.run();
        for(IR_FuncBlock funcBlock : module.getFuncBlocks()) {
            for(IR_BaseBlock irBaseBlock:funcBlock.get_bb_List()){
                ArithmeticOptimizer arithmeticOptimizer = new ArithmeticOptimizer(irBaseBlock);
                arithmeticOptimizer.optimize();
                irBaseBlock.setInstruction_List(arithmeticOptimizer.instructions());
            }
        }
    }

    public void optimize_Gloabal(){
        GlobalArr_To_LocalArr optimizer = new GlobalArr_To_LocalArr();
        optimizer.Optimize(this.module);
    }

    public IR_Module get_module() {
        return module;
    }

    private void addLibs(Scope globalScope) {

        IR_Func getIntType = new IR_Func(i32Type, new ArrayList<>());
        globalScope.add_var("getint", new IR_FuncBlock(getIntType,"getint"));

        IR_Func getchType = new IR_Func(i32Type, new ArrayList<>());
        globalScope.add_var("getch", new IR_FuncBlock(getchType,"getch"));

        IR_Func getFloatType = new IR_Func(floatType,new ArrayList<>());
        globalScope.add_var("getfloat", new IR_FuncBlock(getFloatType, "getfloat"));

        List<IR_Type> getArrayTypeParams = new ArrayList<>();
        getArrayTypeParams.add(new IR_Pointer(i32Type));
        IR_Func getArrayType = new IR_Func(i32Type,getArrayTypeParams);
        globalScope.add_var("getarray", new IR_FuncBlock(getArrayType, "getarray"));

        List<IR_Type> getFArrayTypeParams = new ArrayList<>();
        getFArrayTypeParams.add(new IR_Pointer(floatType));
        IR_Func getFArrayType = new IR_Func(i32Type, getFArrayTypeParams);
        globalScope.add_var("getfarray", new IR_FuncBlock(getFArrayType, "getfarray"));


        List<IR_Type> putIntTypeParams = new ArrayList<>();
        putIntTypeParams.add(i32Type);
        IR_Func putIntType = new IR_Func(voidType, putIntTypeParams);
        globalScope.add_var("putint", new IR_FuncBlock(putIntType, "putint"));

        List<IR_Type> putChTypeParams = new ArrayList<>();
        putChTypeParams.add(i32Type);
        IR_Func putChType = new IR_Func(voidType, putChTypeParams);
        globalScope.add_var("putch", new IR_FuncBlock(putChType, "putch"));

        List<IR_Type> putArrayTypeParams = new ArrayList<>();
        putArrayTypeParams.add(i32Type);
        putArrayTypeParams.add(new IR_Pointer(i32Type));
        IR_Func putArrayType = new IR_Func(voidType, putArrayTypeParams);
        globalScope.add_var("putarray", new IR_FuncBlock(putArrayType, "putarray"));

        List<IR_Type> putFloatTypeParams = new ArrayList<>();
        putFloatTypeParams.add(floatType);
        IR_Func putFloatType = new IR_Func(voidType, putFloatTypeParams);
        globalScope.add_var("putfloat", new IR_FuncBlock(putFloatType, "putfloat"));

        List<IR_Type> putFArrayTypeParams = new ArrayList<>();
        putFArrayTypeParams.add(i32Type);
        putFArrayTypeParams.add(new IR_Pointer(floatType));
        IR_Func putFArrayType = new IR_Func(voidType, putFArrayTypeParams);
        globalScope.add_var("putfarray", new IR_FuncBlock(putFArrayType, "putfarray"));

        List<IR_Type> putFTypeParams = new ArrayList<>();
        putFTypeParams.add(new IR_Pointer(i32Type));
        IR_Func putFType = new IR_Func(voidType, putFTypeParams);
        globalScope.add_var("putf", new IR_FuncBlock(putFType, "putf"));

        List<IR_Type> startTimeTypeParams = new ArrayList<>();
        IR_Func startTimeType = new IR_Func(voidType, startTimeTypeParams);
        globalScope.add_var("starttime", new IR_FuncBlock(startTimeType, "starttime"));

        List<IR_Type> endTimeTypeParams = new ArrayList<>();
        IR_Func endTimeType = new IR_Func(voidType, endTimeTypeParams);
        globalScope.add_var("stoptime", new IR_FuncBlock(endTimeType, "stoptime"));


        IR_Func beforeMainType = new IR_Func(voidType, new ArrayList<>());
        globalScope.add_var("before_main", new IR_FuncBlock(beforeMainType, "before_main"));

        IR_Func afterMainType = new IR_Func(voidType, new ArrayList<>());
        globalScope.add_var("after_main", new IR_FuncBlock(afterMainType, "after_main"));

        List<IR_Type> sysyStartTimeParams = new ArrayList<>();
        sysyStartTimeParams.add(i32Type);
        IR_Func sysyStartTime = new IR_Func(voidType, sysyStartTimeParams);
        globalScope.add_var("_sysy_starttime", new IR_FuncBlock(sysyStartTime, "_sysy_starttime"));

        List<IR_Type> sysyEndTimeParams = new ArrayList<>();
        sysyEndTimeParams.add(i32Type);
        IR_Func sysyEndTime = new IR_Func(voidType, sysyEndTimeParams);
        globalScope.add_var("_sysy_stoptime", new IR_FuncBlock(sysyEndTime, "_sysy_stoptime"));

        List<IR_Type> memsetParams =  Arrays.asList(new IR_Pointer(i32Type),i32Type,i32Type);
        IR_Func memsetType = new IR_Func(voidType, memsetParams);
        globalScope.add_var("memset", new IR_FuncBlock(memsetType, "memset"));
    }

    public IR_Type nametoIRType(String name){
        if(name.equals("int")){
            return i32Type;
        }
        if(name.equals("float")){
            return floatType;
        }
        return voidType;
    }

    public IR_Value visitProgram(SysYParser.ProgramContext ctx) {
        addLibs(this.currentScope);
        IR_Value res = super.visitProgram(ctx);
        return null;
    }

    public IR_Value visitVarDef(SysYParser.VarDefContext ctx) {
        String varName = ctx.Ident().getText();
        if(varName.length() > 20){
            varName = varName.substring(0,20);
        }
        //获取类型
        IR_Type varType = nametoIRType(ctx.getParent().getChild(0).getText());
        IR_Value var;
        IR_Value value;
        //设置初始值为 0
        if(varType instanceof IR_Int32){
            value = i32zero;
        }
        else{
            value = floatZero;
        }
        //对于数组的初始化操作
        //这里面的 exp‘是对于左边的 arr[exp][exp][exp]  这里面的exp ，如果不是数组就不会进去
        List<Integer> num = new ArrayList<>();
        for(SysYParser.ExpContext exp: ctx.exp()){
            IR_Value v1 = visit(exp);
            num.add(Integer.parseInt(v1.get_ValueName()));
        }
        for(int i = num.size() - 1;i >= 0;i--){
            //如果是数组的情况下，类型就不是简单的 int 而是需要转化到指针那一块的类型里面去
            varType = new IR_Array(varType,num.get(i));
        }
        if(varType instanceof IR_Array){
            //存储维度信息
            dimension = ((IR_Array) varType).get_Dimension();
        }
        ArrayList.clear();
        curdimension = 0;
        //如果是全局变量
        if(currentScope.get_fatherScope() == null){
            var = module.add_Var_toGlobal(varName,varType);
            module.addGlobalvar((IR_Global_Value) var);
            //有赋初始值的操作
            if(ctx.Assign()!=null){
                IR_Value value1 = visit(ctx.initVal());
                if(varType instanceof IR_Array){
                    module.array_Init((IR_Global_Value) var,ArrayList);
                }
                else{
                    //初始化值的类型和 定义的类型发生了冲突
                    if(value1.get_Type() != varType){
                        if(varType == floatType){
                            value1 = transfer(builder,value1,IR_Const.IntToFloat);
                        }
                        else if(varType == i32Type){
                            value1 = transfer(builder,value1,IR_Const.FloatToInt);
                        }
                    }
                    module.var_Init((IR_Global_Value)var,value1);
                }
            }
            else{
                //没有初始化的情况下
                if(varType instanceof IR_Array){
                    module.array_Init((IR_Global_Value) var,ArrayList);
                }
                else{
                    module.var_Init((IR_Global_Value)var,value);
                }
            }
        }
        else{
            //此时是对于局部变量的处理
            var = Alloc(builder,varType,varName);
            if(num.isEmpty()){
                //不是数组类型
                if(ctx.Assign()!=null){
                    IR_Value value1 = visit(ctx.initVal());
                    if(value1.get_Type() != varType){
                        if(varType == floatType){
                            value1 = transfer(builder,value1,IR_Const.IntToFloat);
                        }
                        else if(varType == i32Type){
                            value1 = transfer(builder,value1,IR_Const.FloatToInt);
                        }
                    }
                    //var 是声明的 value1是实际的
                    Store(builder,value1,var);
                }
                else{
                    //存储的是 0 没有初始化的时候
                    Store(builder,value,var);
                }
            }
            else{

                //数组类型
                if(ctx.Assign() != null){
                    if(!ctx.initVal().isEmpty()){
                        ((IR_Array)((IR_Pointer)var.get_Type()).get_Base_Type()).setInit(true);
                        //强转到数组初始化里面去
                        visitInitList((SysYParser.InitListContext)ctx.initVal());

                        List<IR_Value> arrayPointer = new ArrayList<>(dimension.size());//存储数组的指针
                        //@memset(i32*, i32, i32)
                        String funcname = "memset";
                        IR_FuncBlock func = (IR_FuncBlock) currentScope.findinAll(funcname);
                        List<IR_Value> args = new ArrayList<>();
                        args.add(var);
                        args.add(i32zero);
                        int number = dimension.get(0);
                        for(int i = 1; i < dimension.size();i++){
                            number *= dimension.get(i);
                        }
                        // int float 占据 四字节
                        number *= 4;
                        args.add(new IR_Int_Value(number,i32Type));
                        //Store(builder, 0, elementPtr);

                        arrayPointer = new ArrayList<>(dimension.size());//存储数组的指针
                        for (int i = 0; i < ArrayList.size(); i++) {
                            int totalCount = ArrayList.size();//总元素个数
                            int counter = i;//当前元素的下标
                            if (i == 0 || !Objects.equals(ArrayList.get(i).get_ValueName(), "0")) {//如果当前初始化值不为0
                                arrayPointer.add(i32zero);
                                //比如 三维数组 [2][3][4]（总元素数=24），初始化索引 i=10：
                                //第一维步长 = 24 / 2 = 12 → 坐标 = 10 / 12 = 0  剩余索引 = 10 % 12 = 10
                                //第二维步长 = 12 / 3 = 4 → 坐标 = 10 / 4 = 2    剩余索引 = 10 % 4 = 2
                                //第三维步长 = 4 / 4 = 1 → 坐标 = 2 / 1 = 2  结果坐标：[0][2][2]
                                for (Integer integer : dimension) {//遍历数组的维度
                                    totalCount /= integer;//计算当前维度的元素个数
                                    arrayPointer.add(new IR_Int_Value(counter / totalCount, i32Type));
                                    counter -= (counter / totalCount) * totalCount;
                                }
                                int counter1 = 1;
                                List<IR_Value> paramList = new ArrayList<>();
                                paramList.add(i32zero);
                                paramList.add(arrayPointer.get(counter1++));
                                // 第一层：获取当前维度的子数组指针
                                IR_Value elementPtr = Get_Pointer(builder, var, paramList, paramList.size(), "array");
                                //获取后续指针
                                for (int j = 0; j < dimension.size() - 1; j++) {
                                    paramList.clear();
                                    paramList.add(i32zero);
                                    paramList.add(arrayPointer.get(counter1++));
                                    elementPtr = Get_Pointer(builder, elementPtr, paramList, paramList.size(), "array");
                                }
                                if(i == 0){
                                    IR_Value newelementPtr = elementPtr;
                                    if(((IR_Pointer)newelementPtr.get_Type()).get_Base_Type().equals(floatType)){
                                        //((IR_Pointer)newelementPtr.get_Type()).set_Base_Type(i32Type);
                                        //float 转 i32
                                        newelementPtr = transfer(builder,newelementPtr, IR_Const.BITCAST);
                                    }
                                    args.set(0,newelementPtr);
                                    Call(builder,func,args,args.size(),funcname);
                                }
                                if(!Objects.equals(ArrayList.get(i).get_ValueName(), "0")) {
                                    Store(builder, ArrayList.get(i), elementPtr);
                                }
                                arrayPointer.clear();
                            }
                        }
                    }
                }
            }


        }
        currentScope.add_var(varName,var);
        return null;
    }

    public IR_Value visitInit(SysYParser.InitContext ctx) {
        return ctx.exp().accept(this);
    }

    public IR_Value visitInitList(SysYParser.InitListContext ctx) {
        // 处理initVal嵌套的情况
        int layerDim = curdimension;
        boolean dump = false;
        int count = 0; // 本层已有的数目
        int fullCount = 0; // 需要进到上一层的数目
        for (SysYParser.InitValContext initValContext : ctx.initVal()) {
            if (initValContext instanceof SysYParser.InitContext) {
                // 没有{}的处理
                if (!dump) {
                    dump = true;
                    curdimension = dimension.size() - 1;
                    count = 0;
                    fullCount = dimension.get(curdimension);
                }
                ArrayList.add(((SysYParser.InitContext)initValContext).exp().accept(this));
            } else {
                int tmpDim = curdimension;
                curdimension = tmpDim + 1;
                visitInitList((SysYParser.InitListContext)initValContext);
                curdimension = tmpDim;
            }
            count++;
            if (count == fullCount) {
                dump = false;
                curdimension--;
                if (curdimension <= layerDim) curdimension = layerDim;
                fullCount = dimension.get(curdimension);
                int layerParamCount = 1;
                for (int i = curdimension + 1; i < dimension.size(); i++) layerParamCount *= dimension.get(i);
                count = ArrayList.size() / layerParamCount;
            }
        }
        int totalParamCount = 1;
        for (int i = layerDim; i < dimension.size(); i++) {
            totalParamCount *= dimension.get(i);
        }
        boolean empty = (ctx.initVal().isEmpty());
        if (ArrayList.size() % totalParamCount != 0 || empty) {
            for (int i = ArrayList.size() % totalParamCount; i < totalParamCount; i++) ArrayList.add(i32zero);
        }
        return null;
    }


    public IR_Value visitConstDef(SysYParser.ConstDefContext ctx) {
        String varname = ctx.Ident().getText();
        if(varname.length() > 20){
            varname = varname.substring(0,20);
        }
        //child 0 是 const
        IR_Type vartype = nametoIRType(ctx.getParent().getChild(1).getText());
        IR_Value var = null;
        IR_Value init = null;
        if(vartype instanceof IR_Int32){
            init = i32zero;
        }
        else{
            init = floatZero;
        }
        //对于数组的初始化操作
        //这里面的 exp‘是对于左边的 arr[exp][exp][exp]  这里面的exp ，如果不是数组就不会进去
        List<Integer> num = new ArrayList<>();
        for(SysYParser.ExpContext exp: ctx.exp()){
            IR_Value v1 = visit(exp);
            num.add(Integer.parseInt(v1.get_ValueName()));
        }
        for(int i = num.size() - 1;i >= 0;i--){
            //如果是数组的情况下，类型就不是简单的 int 而是需要转化到指针那一块的类型里面去
            vartype = new IR_Array(vartype,num.get(i));
        }
        if(vartype instanceof IR_Array){
            //存储维度信息
            dimension = ((IR_Array) vartype).get_Dimension();
        }
        ArrayList.clear();
        curdimension = 0;

        if(currentScope.get_fatherScope() == null){
            var = module.add_Var_toGlobal(varname,vartype);
            module.addGlobalvar((IR_Global_Value) var);
            //有赋初始值的操作
            if(ctx.Assign()!=null){
                IR_Value value1 = visit(ctx.initVal());
                if(vartype instanceof IR_Array){
                    module.array_Init((IR_Global_Value) var,ArrayList);
                }
                else{
                    //初始化值的类型和 定义的类型发生了冲突
                    if(value1.get_Type() != vartype){
                        //此处不需要转化的 汇编代码
                        if(value1.get_Type() == floatType){
                            int i = (int)((IR_Float_Value)value1).get_Float_Value();
                            value1 = new IR_Int_Value(i,i32Type);
                        }
                        else if(value1.get_Type() == i32Type){
                            value1 = new IR_Float_Value(Float.parseFloat(value1.get_ValueName()));
                        }
                    }
                    if(value1 instanceof IR_Int_Value){
                        ConstIntVarMap.put(var.get_ValueName(),((IR_Int_Value) value1).get_Int_Value());
                    }
                    if(value1 instanceof IR_Float_Value){
                        ConstFloatVarMap.put(var.get_ValueName(),((IR_Float_Value) value1).get_Float_Value());
                    }
                    module.var_Init((IR_Global_Value)var,value1);
                }
            }
            else{
                //没有初始化的情况下
                if(vartype instanceof IR_Array){
                    module.array_Init((IR_Global_Value) var,ArrayList);
                }
                else{
                    if(init instanceof IR_Int_Value){
                        ConstIntVarMap.put(var.get_ValueName(),Integer.parseInt(init.get_ValueName()));
                    }
                    if(init instanceof IR_Float_Value){
                        ConstFloatVarMap.put(var.get_ValueName(),Float.parseFloat(init.get_ValueName()));
                    }
                    module.var_Init((IR_Global_Value)var,init);
                }
            }
        }
        else{
            //此时是对于局部变量的处理
            var = Alloc(builder,vartype,varname);
            if(num.isEmpty()){
                //不是数组类型
                if(ctx.Assign()!=null){
                    IR_Value value1 = visit(ctx.initVal());
                    if(value1.get_Type() != vartype){
                        if(vartype == floatType){
                            value1 = transfer(builder,value1,IR_Const.IntToFloat);
                        }
                        else if(vartype == i32Type){
                            value1 = transfer(builder,value1,IR_Const.FloatToInt);
                        }
                    }
                    //var 是声明的 value1是实际的
                    Store(builder,value1,var);
                    if(value1 instanceof IR_Int_Value){
                        ConstIntVarMap.put(var.get_ValueName(),Integer.parseInt(value1.get_ValueName()));
                    }
                    if(value1 instanceof IR_Float_Value) {
                        String numm = value1.get_ValueName();
                        if (numm.startsWith("0x") || numm.startsWith("0X")) {
                            //说明此时就是浮点数转浮点数
                            ConstFloatVarMap.put(var.get_ValueName(), ((IR_Float_Value) value1).get_Float_Value());
                        } else {
                            ConstFloatVarMap.put(var.get_ValueName(), Float.parseFloat(numm));
                        }
                    }
                }
                else{
                    //存储的是 0
                    Store(builder,init,var);
                    if(init instanceof IR_Int_Value){
                        ConstIntVarMap.put(var.get_ValueName(),Integer.parseInt(init.get_ValueName()));
                    }
                    if(init instanceof IR_Float_Value){
                        ConstFloatVarMap.put(var.get_ValueName(),Float.parseFloat(init.get_ValueName()));
                    }
                }
            }
            else{

                //数组类型
                if(ctx.Assign() != null){
                    if(!ctx.initVal().isEmpty()){
                        ((IR_Array)((IR_Pointer)var.get_Type()).get_Base_Type()).setInit(true);
                        //强转到数组初始化里面去
                        visitInitList((SysYParser.InitListContext)ctx.initVal());

                        List<IR_Value> arrayPointer = new ArrayList<>(dimension.size());//存储数组的指针
                        for (int i = 0; i < ArrayList.size(); i++) {
                            int totalCount = ArrayList.size();//总元素个数
                            int counter = i;//当前元素的下标
                            if (!Objects.equals(ArrayList.get(i).get_ValueName(), "0")) {//如果当前初始化值不为0
                                arrayPointer.add(i32zero);
                                //比如 三维数组 [2][3][4]（总元素数=24），初始化索引 i=10：
                                //第一维步长 = 24 / 2 = 12 → 坐标 = 10 / 12 = 0  剩余索引 = 10 % 12 = 10
                                //第二维步长 = 12 / 3 = 4 → 坐标 = 10 / 4 = 2    剩余索引 = 10 % 4 = 2
                                //第三维步长 = 4 / 4 = 1 → 坐标 = 2 / 1 = 2  结果坐标：[0][2][2]
                                for (Integer integer : dimension) {//遍历数组的维度
                                    totalCount /= integer;//计算当前维度的元素个数
                                    arrayPointer.add(new IR_Int_Value(counter / totalCount, i32Type));
                                    counter -= (counter / totalCount) * totalCount;
                                }
                                int counter1 = 1;
                                List<IR_Value> paramList = new ArrayList<>();
                                paramList.add(i32zero);
                                paramList.add(arrayPointer.get(counter1++));
                                // 第一层：获取当前维度的子数组指针
                                IR_Value elementPtr = Get_Pointer(builder, var, paramList, paramList.size(), "array");
                                //获取后续指针
                                for (int j = 0; j < dimension.size() - 1; j++) {
                                    paramList.clear();
                                    paramList.add(i32zero);
                                    paramList.add(arrayPointer.get(counter1++));
                                    elementPtr = Get_Pointer(builder, elementPtr, paramList, paramList.size(), "array");
                                }

                                Store(builder, ArrayList.get(i), elementPtr);
                                arrayPointer.clear();
                            }
                        }
                    }
                }
            }


        }
        currentScope.add_var(varname,var);
        return null;
    }

    public IR_Value visitNumber(SysYParser.NumberContext ctx) {
        String num = ctx.getText();
        if(ctx.intConst() != null){
            long number;
            if (num.startsWith("0x") || num.startsWith("0X")) {
                number = Long.parseLong(num.substring(2), 16);
            } else if (num.startsWith("0") && num.length() != 1) {
                number = Long.parseLong(num.substring(1), 8);
            } else {
                number = Long.parseLong(num);
            }
            return new IR_Int_Value(number, i32Type);
        }
        else if(ctx.floatConst() != null){
            float number = (float) Double.parseDouble(num);
            return new IR_Float_Value(number);
        }
        return new IR_Int_Value(0, i32Type);
    }

    public IR_Value visitFuncDef(SysYParser.FuncDefContext ctx) {
        //访问函数定义  首先分析函数的返回
        IR_Type returnstmt;
        if("int".equals(ctx.funcType().getText())){
            //返回类型是整数
            returnstmt = i32Type;
        }
        else if("float".equals(ctx.funcType().getText())){
            //返回类型是浮点数
            returnstmt = floatType;
        }
        else{
            // void 类型
            returnstmt = voidType;
        }
        IR_Func func_type;
        //处理函数参数
        if(ctx.funcFParams() != null){
            int argsnum = ctx.funcFParams().funcFParam().size();
            List<IR_Type> argstype = new ArrayList<>();
            for (int i = 0; i < argsnum; i++) {
                //参数是数组类型
                if(ctx.funcFParams().funcFParam(i) instanceof SysYParser.ArrayParamContext){
                    SysYParser.ArrayParamContext newctx = (SysYParser.ArrayParamContext)ctx.funcFParams().funcFParam(i);
                    if(newctx.Lbracket().size() == 1){
                        //处理一维数组的情况
                        argstype.add(new IR_Pointer(nametoIRType(newctx.bType().getText())));
                    }
                    else{
                        //参数是多维数组的情况
                        IR_Type tmptype = nametoIRType(newctx.bType().getText());
                        for(int j = newctx.Lbracket().size() - 1;j >= 1;j--){
                            //第0 维度不存在 exp 所以下标还需要 -1
                            IR_Value tmpvalue = newctx.exp(j - 1).accept(this);
                            if(tmpvalue instanceof IR_Int_Value){
                                tmptype = new IR_Array(tmptype,Integer.parseInt(tmpvalue.get_ValueName()));
                            }
                            else{
                                tmptype = new IR_Array(tmptype,Integer.parseInt(newctx.exp(j - 1).getText()));
                            }
                        }
                        argstype.add(new IR_Pointer(tmptype));
                    }
                }
                else{
                    //不是数组类型
                    SysYParser.ScalarParamContext newctx = (SysYParser.ScalarParamContext)ctx.funcFParams().funcFParam(i);
                    argstype.add(nametoIRType(newctx.bType().getText()));
                }
            }
            func_type = new IR_Func(returnstmt,argstype);
        }
        else{
            func_type = new IR_Func(returnstmt,new ArrayList<>());
        }

        //然后添加函数块
        IR_FuncBlock fb = new IR_FuncBlock(func_type,ctx.Ident().getText());

        module.add_FunctoModule(fb);
        currentFunction = fb;
        String funcname = ctx.Ident().getText() + "Entry";
        currentBlockName = funcname;
        IR_BaseBlock baseBlock = IR_BaseBlock.add_Baseblock(fb,funcname,currentScope.getDep());
        IR_Atend(builder,baseBlock);
        currentBlock = baseBlock;
        currentScope = new Scope(currentScope,currentBlockName,baseBlock);

        //处理参数信息
        int argsnum = fb.get_params().size();
        List<IR_Value> vlist = new ArrayList<>();
        for (int i = 0; i < argsnum; i++) {
            String argname = null;
            IR_Type argtype = fb.get_param(i).get_Type();
            if(ctx.funcFParams().funcFParam(i) instanceof SysYParser.ArrayParamContext){
                SysYParser.ArrayParamContext newctx = (SysYParser.ArrayParamContext)ctx.funcFParams().funcFParam(i);
                argname = newctx.Ident().getText();
            }
            else{
                //不是数组类型
                SysYParser.ScalarParamContext newctx = (SysYParser.ScalarParamContext)ctx.funcFParams().funcFParam(i);
                argname = newctx.Ident().getText();
            }
            IR_Value V = Alloc(builder,argtype,argname);
            vlist.add(V);
            currentScope.add_var(argname,V);
        }
        for (int i = 0; i < argsnum; i++) {
            Store(builder,fb.get_param(i),vlist.get(i));
        }
        //访问函数体
        visitBlock(ctx.block());

        //加入ret void

        boolean hasret = false;
        for (int i = 0; i < ctx.block().blockItem().size(); i++) {
            if(ctx.block().blockItem(i).stmt() instanceof SysYParser.ReturnContext){
                hasret = true;
                break;
            }
        }
        if(!hasret){
            if(returnstmt == i32Type){
                Ret(builder,i32zero);
            }
            else if(returnstmt == floatType){
                Ret(builder,floatZero);
            }
            else{
                Ret(builder,null);
            }
        }

        //函数访问结束，切换作用域
        currentScope = currentScope.get_fatherScope();
        return null;
    }

    public IR_Value visitBlock(SysYParser.BlockContext ctx) {
        //修改scope的名字
        currentBlockName = currentBlockName + localScopeCounter;
        localScopeCounter++;
        currentScope = new Scope(currentScope,currentBlockName,currentBlock);
        IR_Value ret = super.visitBlock(ctx);
        currentScope = currentScope.get_fatherScope();
        iscontinue = false;
        isbreak = false;
        return ret;
    }

    public IR_Value visitReturn(SysYParser.ReturnContext ctx) {
        if(ctx.exp() != null){
            IR_Value ans = visit(ctx.exp());
            IR_Type rettype = currentFunction.get_RetType();
            if(null != ans && !rettype.equals(ans.get_Type())){
                //需要进行类型转化
                if(i32Type.equals(rettype)){
                    ans = transfer(builder,ans,IR_Const.FloatToInt);
                }
                else if(floatType.equals(rettype)){
                    ans = transfer(builder,ans,IR_Const.IntToFloat);
                }
            }
            return Ret(builder,ans);
        }
        return Ret(builder,null);
    }

    public IR_Value visitAssign(SysYParser.AssignContext ctx) {
        IR_Value lval = visitLVal(ctx.lVal());
        //访问右值
        IR_Value rVal = visit(ctx.exp());
        IR_Type lvaltype = null;
        if(lval.get_Type() instanceof IR_Pointer){
            lvaltype = ((IR_Pointer) lval.get_Type()).get_Base_Type();
        }
        else{
            lvaltype = lval.get_Type();
        }

        if(!lvaltype.equals(rVal.get_Type())){
            //类型转换
            if(i32Type.equals(lvaltype)){
                rVal = transfer(builder,rVal,IR_Const.FloatToInt);
            }else if(floatType.equals(lvaltype)){
                rVal = transfer(builder,rVal,IR_Const.IntToFloat);
            }
        }
        return Store(builder,rVal,lval);
    }

    public IR_Value visitLVal(SysYParser.LValContext ctx) {
        String lvalname = ctx.Ident().getText();
        if(lvalname.length() > 20){
            lvalname = lvalname.substring(0,20);
        }
        IR_Value lvalvalue = currentScope.findinAll(lvalname);
        IR_Type lvaltype = null;
        if(lvalvalue.get_Type() instanceof IR_Pointer){
            lvaltype = ((IR_Pointer) lvalvalue.get_Type()).get_Base_Type();
        }
        else{
            lvaltype = lvalvalue.get_Type();
        }
        lvaltype = lvaltype instanceof IR_Func ? ((IR_Func) lvaltype).get_Return_Type() : lvaltype;
        //常量直接返回
        if(lvaltype == i32Type || lvaltype == floatType){
            return lvalvalue;
        }
        if(new IR_Pointer(i32Type).get_TypeName().equals(lvaltype.get_TypeName()) || new IR_Pointer(floatType).get_TypeName().equals(lvaltype.get_TypeName())){
            if(ctx.exp() == null){
                //变量
                return lvalvalue;
            }else{
                if(ctx.exp().size() == 1) {
                    //一维数组
                    List<IR_Value> indexs = new ArrayList<>();
                    IR_Value index = ctx.exp(0).accept(this);
                    indexs.add(index);
                    IR_Value pointer = Load(builder, lvalname, lvalvalue);
                    lvalvalue = Get_Pointer(builder, pointer, indexs, indexs.size(), lvalname);
                }
            }
        }else if(lvaltype instanceof IR_Pointer && (((IR_Pointer) lvaltype).get_Base_Type() instanceof IR_Array || ((IR_Pointer) lvaltype).get_Base_Type() instanceof IR_Pointer)){
            //多维度数组
            // 此处不能 使用 == null 即使为空的时候也会创建一个 arraylist 存在对象，需要使用empty判断
            if(ctx.exp().isEmpty()){
                return lvalvalue;
            }
            else{
                List<IR_Value> indexs = new ArrayList<>();
                IR_Value index = ctx.exp(0).accept(this);
                indexs.add(index);
                IR_Value pointer = Load(builder, lvalname, lvalvalue);
                lvalvalue = Get_Pointer(builder, pointer, indexs, indexs.size(), lvalname);
                for (int i = 1; i < ctx.exp().size(); i++) {
                    List<IR_Value> ll = new ArrayList<>();
                    IR_Value tmpl = ctx.exp(i).accept(this);
                    ll.add(i32zero);
                    ll.add(tmpl);
                    lvalvalue = Get_Pointer(builder,lvalvalue,ll, ll.size(), lvalname);
                }
            }
        }else{
            if(ctx.exp() == null){
                List<IR_Value> ll = new ArrayList<>();
                ll.add(i32zero);
                ll.add(i32zero);
                lvalvalue = Get_Pointer(builder,lvalvalue,ll,ll.size(),lvalname);
                arrayAddr = true;
                return lvalvalue;
            }

            for(SysYParser.ExpContext e:ctx.exp()){
                List<IR_Value> ll = new ArrayList<>();
                if(lvaltype instanceof IR_Array){
                    ll.add(i32zero);
                }
                IR_Value tmpl = e.accept(this);
                ll.add(tmpl);
                lvalvalue = Get_Pointer(builder,lvalvalue,ll, ll.size(), lvalname);
            }
        }
        IR_Type newlvaltype = lvalvalue.get_Type();
        if(newlvaltype instanceof IR_Array || (newlvaltype instanceof IR_Pointer) && ((IR_Pointer) newlvaltype).get_Base_Type() instanceof IR_Array){
            arrayAddr = true;
        }
        return lvalvalue;
    }

    public IR_Value visitLvalexp(SysYParser.LvalexpContext ctx) {

        String name = ctx.lVal().Ident().getText();
        if(name.length() > 20){
            name = name.substring(0,20);
        }
        IR_Value value = currentScope.findinAll(name);
        //如果已经是常量的情况下
        if(ConstIntVarMap.get(value.get_ValueName()) != null){
            return new IR_Int_Value(ConstIntVarMap.get(value.get_ValueName()),i32Type);
        }
        if(ConstFloatVarMap.get(value.get_ValueName()) != null){
            return new IR_Float_Value(ConstFloatVarMap.get(value.get_ValueName()));
        }
        IR_Value lval = visitLVal(ctx.lVal());
        if(arrayAddr){
            arrayAddr = false;
            return lval;
        }
        return Load(builder,name,lval);
    }

    /*public IR_Value visitAddandsubexp(SysYParser.AddandsubexpContext ctx) {
        //生成加减乘除的返回值
        if("+".equals(ctx.getChild(1).getText())){
            return Add(builder,visit(ctx.exp(0)),visit(ctx.exp(1)),"add");
        }
        else {
            return Sub(builder,visit(ctx.exp(0)),visit(ctx.exp(1)),"sub");
        }
    }*/
    public IR_Value visitAddandsubexp(SysYParser.AddandsubexpContext ctx) {
        //生成加减乘除的返回值

        // 1. 扁平化：收集所有 term 和 ops
        List<SysYParser.ExpContext> terms = new ArrayList<>();
        List<TerminalNode>  ops   = new ArrayList<>();
        collectAddSub(ctx, terms, ops);

        // 2. 先处理第一个 term
        IR_Value result = visit(terms.get(0));

        // 3. 依次 apply 剩余的 ops
        for (int i = 0; i < ops.size(); i++) {
            IR_Value right = visit(terms.get(i + 1));
            TerminalNode op = ops.get(i);
            if (op.getSymbol().getType() == SysYParser.Add) {
                result = Add(builder, result, right, "add");
            } else { // Sub
                result = Sub(builder, result, right, "sub");
            }
        }
        return result;
    }

    // 辅助函数：把 ctx 这一棵左递归树，摊平成 terms/ops
    private void collectAddSub(
            SysYParser.ExpContext e,
            List<SysYParser.ExpContext> terms,
            List<TerminalNode> ops
    ) {
        if (e instanceof SysYParser.AddandsubexpContext) {
            SysYParser.AddandsubexpContext ctx = (SysYParser.AddandsubexpContext) e;
            // 先递归左支
            collectAddSub(ctx.exp(0), terms, ops);
            // 再把本层的右支和运算符记下来
            terms.add(ctx.exp(1));
            // ctx.Add() 或 ctx.Sub() 会返回相应的 TerminalNode
            ops.add(ctx.Add() != null ? ctx.Add() : ctx.Sub());
        } else {
            // 递归到底，非 add/sub（比如 symbolexp、unaryOpexp、numexp……）
            terms.add(e);
        }
    }

    /*public IR_Value visitSymbolexp(SysYParser.SymbolexpContext ctx) {
        if("*".equals(ctx.getChild(1).getText())){
            return Mul(builder,visit(ctx.exp(0)),visit(ctx.exp(1)),"mul");
        }
        else if("/".equals(ctx.getChild(1).getText())){
            return Div(builder,visit(ctx.exp(0)),visit(ctx.exp(1)),"div");
        }
        else{
            return Rem(builder,visit(ctx.exp(0)),visit(ctx.exp(1)),"rem");
        }
    }*/

    @Override
    public IR_Value visitSymbolexp(SysYParser.SymbolexpContext ctx) {
        // 1. 拆分 exp 和运算符（Mul / Div / Mod）
        List<SysYParser.ExpContext> terms = new ArrayList<>();
        List<TerminalNode> ops = new ArrayList<>();

        collectMulDivMod(ctx, terms, ops);

        // 2. 处理第一个 term
        IR_Value result = visit(terms.get(0));

        // 3. 顺序 apply 运算符
        for (int i = 0; i < ops.size(); i++) {
            IR_Value rhs = visit(terms.get(i + 1));
            TerminalNode op = ops.get(i);
            int opType = op.getSymbol().getType();

            if (opType == SysYParser.Mul) {
                result = Mul(builder, result, rhs, "mul");
            } else if (opType == SysYParser.Div) {
                result = Div(builder, result, rhs, "div");
            } else { // SysYParser.Mod
                result = Rem(builder, result, rhs, "rem");
            }
        }

        return result;
    }

    private void collectMulDivMod(
            SysYParser.ExpContext e,
            List<SysYParser.ExpContext> terms,
            List<TerminalNode> ops
    ) {
        if (e instanceof SysYParser.SymbolexpContext) {
            SysYParser.SymbolexpContext ctx = (SysYParser.SymbolexpContext) e;
            // 递归左边
            collectMulDivMod(ctx.exp(0), terms, ops);
            // 当前操作符和右侧
            terms.add(ctx.exp(1));
            if (ctx.Mul() != null) {
                ops.add(ctx.Mul());
            } else if (ctx.Div() != null) {
                ops.add(ctx.Div());
            } else {
                ops.add(ctx.Mod());
            }
        } else {
            // 最底层了，非 Mul/Div/Mod 表达式
            terms.add(e);
        }
    }


    public IR_Value visitUnaryOpexp(SysYParser.UnaryOpexpContext ctx) {
        IR_Value ans = visit(ctx.exp());
        if("!".equals(ctx.getChild(0).getText())){
            // 0 -> 1  1->0  LLVM IR的常见技巧
            ans = Icmp(builder,new IR_Int_Value(0,i32Type),ans, IR_NE,"icmp");
            ans = Xor(builder,ans,new IR_Int_Value(1,i1Type),"xor");
            ans = Zext(builder,ans,i32Type,"zext");
            return ans;
        }
        else if("-".equals(ctx.getChild(0).getText())){
            return Neg(builder,ans,"neg");
        }
        else{
            return ans;
        }
    }

    public IR_Value visitParenexp(SysYParser.ParenexpContext ctx) {
        return visit(ctx.exp());
    }

    public IR_Value visitFuncRParamsexp(SysYParser.FuncRParamsexpContext ctx) {
        String funcname = ctx.Ident().getText();
        IR_FuncBlock func = module.get_func_byName(funcname);
        if(func == null){
            func = (IR_FuncBlock)currentScope.findinAll(funcname);
        }
        int argsnum = func.get_params().size();
        if("starttime".equals(funcname) || "stoptime".equals(funcname)){
            funcname = "_sysy_" + funcname;
            IR_Value v = new IR_Int_Value(ctx.getStart().getLine(),i32Type);
            List<IR_Value> args = new ArrayList<>();
            args.add(v);
            func = (IR_FuncBlock) currentScope.findinAll(funcname);
            return Call(builder,func,args,args.size(),funcname);
        }
        //函数调用
        List<IR_Value> args = new ArrayList<>();
        for (int i = 0; i < argsnum; i++) {
            IR_Value para = ctx.funcRParams().funcRParam(i).accept(this);
            IR_Type paratype = ((IR_Func)func.get_Type()).get_Param_Type(i);
            //这部分代码处理函数参数中的指针类型。如果参数类型是指针类型，代码会检查是否是数组指针类型，如果是，则调用 Get_Pointer() 方法进行适当的指针转换
            if(paratype instanceof IR_Pointer){
                // 情况1：形参是基础指针，但实参是数组指针
                if(!(((IR_Pointer) paratype).get_Base_Type() instanceof IR_Array)
                        && para.get_Type() instanceof IR_Pointer
                        && ((IR_Pointer) para.get_Type()).get_Base_Type() instanceof IR_Array){
                    List<IR_Value> list = new ArrayList<>();
                    list.add(i32zero);
                    list.add(i32zero);
                    para = Get_Pointer(builder,para,list,list.size(),"new_ptr");
                }// 情况2：指针类型不匹配
                else if(!Objects.equals(paratype.get_TypeName(),para.get_Type().get_TypeName())){
                    List<IR_Value> list = new ArrayList<>();
                    list.add(i32zero);
                    list.add(i32zero);
                    para = Get_Pointer(builder,para,list,list.size(),"new_ptr");
                }
            }

            if(!paratype.equals(para.get_Type())){
                //类型转化
                if(i32Type.equals(paratype)){
                    para = transfer(builder,para, IR_Const.FloatToInt);
                }
                else if(floatType.equals(paratype)){
                    para = transfer(builder,para,IR_Const.IntToFloat);
                }
            }
            args.add(i,para);
        }
        return Call(builder,func,args,args.size(),funcname);
    }

    public IR_Value visitCond(SysYParser.CondContext ctx) {
        IR_Value ans = null;
        if(ctx.exp() != null){
            ans = visit(ctx.exp());
        }
        else{
            String chosen = ctx.getChild(1).getText();
            switch(chosen){
                case EQ:
                    ans = Icmp(builder,visit(ctx.cond(0)),visit(ctx.cond(1)),IR_EQ,"eq_cond");
                    break;
                case NE:
                    ans = Icmp(builder,visit(ctx.cond(0)),visit(ctx.cond(1)),IR_NE,"ne_cond");
                    break;
                case GT:
                    ans = Icmp(builder,visit(ctx.cond(0)),visit(ctx.cond(1)),IR_GT,"gt_cond");
                    break;
                case LT:
                    ans = Icmp(builder,visit(ctx.cond(0)),visit(ctx.cond(1)),IR_LT,"lt_cond");
                    break;
                case GEQ:
                    ans = Icmp(builder,visit(ctx.cond(0)),visit(ctx.cond(1)),IR_GEQ,"geq_cond");
                    break;
                case LEQ:
                    ans = Icmp(builder,visit(ctx.cond(0)),visit(ctx.cond(1)),IR_LEQ,"leq_cond");
                    break;
                case AND:
                    IR_BaseBlock iftrue = IR_BaseBlock.add_Baseblock(currentFunction,"and_true",currentScope.getDep());
                    //tmpbb 主要维护的是 多个&& 左递归的时候 前面的如果成功需要跳转到下一个，而最后一个要跳到外面
                    IR_BaseBlock tmpbb = trueblock;
                    trueblock = iftrue;
                    IR_Value cond1 = visit(ctx.cond(0));
                    cond1 = Icmp(builder,cond1,i32zero,IR_NE,"ne_cond");
                    //三个关键基本块：and_true：条件1为真时需计算条件2 and_false：条件1为假时直接返回假 and_cond：最终结果合并点
                    //根据cond1的值跳转到不同分支
                    Cond(builder,cond1,iftrue,falseblock);
                    //分支 true
                    IR_Atend(builder,iftrue);
                    currentBlock = iftrue;
                    currentBlockName = "iftrue";

                    trueblock = tmpbb;

                    IR_Value cond2 = visit(ctx.cond(1));
                    if(cond2 instanceof IR_Float_Value){
                        cond2 = Icmp(builder,cond2,i32zero,IR_NE,"ne_tmp");
                        cond2 = Zext(builder,cond2,i32Type,"zext_tmp");
                    }
                    return cond2;
                case OR:
                    IR_BaseBlock oriffalse = IR_BaseBlock.add_Baseblock(currentFunction,"or_false",currentScope.getDep());
                    //维护左递归 || 第一个失败了可以跳转到 orfalse  但是第二个失败了就必须结束了
                    IR_BaseBlock tmpbb1 = falseblock;
                    falseblock = oriffalse;

                    IR_Value orcond1 = visit(ctx.cond(0));
                    cond1 = Icmp(builder,orcond1,i32zero,IR_NE,"ne_cond");
                    Cond(builder,cond1,trueblock,oriffalse);
                    //分支 true
                    //分支false
                    IR_Atend(builder,oriffalse);
                    currentBlock = oriffalse;
                    currentBlockName = "iffalse";

                    falseblock = tmpbb1;

                    IR_Value orcond2 = visit(ctx.cond(1));
                    if(orcond2 instanceof IR_Float_Value){
                        orcond2 = Icmp(builder,orcond2,i32zero,IR_NE,"ne_tmp");
                        orcond2 = Zext(builder,orcond2,i32Type,"zext_tmp");
                    }
                    return orcond2;
            }
        }
        if(i1Type.equals(ans.get_Type())){
            ans = Zext(builder,ans,i32Type,"zext");
        }
        return ans;
    }

    public IR_Value visitIfElse(SysYParser.IfElseContext ctx) {
        IR_BaseBlock tmpcurrentbb = currentBlock;
        IR_BaseBlock iftrue = IR_BaseBlock.add_Baseblock(currentFunction, "iftrue", currentScope.getDep());
        trueblock = iftrue;
        IR_BaseBlock iffalse = null;
        IR_BaseBlock ifentry = null;
        if(ctx.stmt().size() == 2){
            iffalse = IR_BaseBlock.add_Baseblock(currentFunction, "iffalse", currentScope.getDep());
            ifentry = IR_BaseBlock.add_Baseblock(currentFunction, "ifentry", currentScope.getDep());
            falseblock = iffalse;
        }
        else{
            ifentry = IR_BaseBlock.add_Baseblock(currentFunction, "ifentry", currentScope.getDep());
            falseblock = ifentry;
        }
        IR_Value ans = visit(ctx.cond());
        //  i32 -> i1
        if (i32Type.equals(ans.get_Type())) {
            ans = Icmp(builder, i32zero, ans, IR_NE, "ne_tmp");
        }
        if (ans instanceof IR_Float_Value) {
            ans = Icmp(builder, ans, i32zero, IR_NE, "ne_tmp");
        }

        if(ctx.stmt().size() == 2) {
            //if else 都存的情况下
            tmpcurrentbb = currentBlock;
            Cond(builder, ans, iftrue, iffalse);
            IR_Atend(builder, iftrue);
            currentBlock = iftrue;
            currentBlockName = "iftrue";
            visit(ctx.stmt(0));
            //让 true的后继是entry
            if (!(iscontinue || isbreak)) {
                Br(builder, ifentry);
                IR_Atend(builder, ifentry);
                iscontinue = false;
                isbreak = false;
            }

            setbuilderbb(builder, tmpcurrentbb);
            IR_Atend(builder, iffalse);
            currentBlock = iffalse;
            currentBlockName = "iffalse";
            visit(ctx.stmt(1));
            if (!(iscontinue || isbreak)) {
                Br(builder, ifentry);
                IR_Atend(builder, ifentry);
                iscontinue = false;
                isbreak = false;
            }
            setbuilderbb(builder, ifentry);

            currentBlock = ifentry;
            currentBlockName = "ifentry";
        }
        else{
            Cond(builder, ans, iftrue, ifentry);

            tmpcurrentbb = currentBlock;
            IR_Atend(builder, iftrue);
            currentBlock = iftrue;
            currentBlockName = "iftrue";
            visit(ctx.stmt(0));
            Br(builder, ifentry);

            setbuilderbb(builder, tmpcurrentbb);
            IR_Atend(builder, ifentry);

            currentBlock = ifentry;
            currentBlockName = "ifentry";
        }
        trueblock=null;
        falseblock=null;
        return null;
    }

    public IR_Value visitWhile(SysYParser.WhileContext ctx) {
        IR_BaseBlock whilecondblock = IR_BaseBlock.add_Baseblock(currentFunction,"whilecond",currentScope.getDep());
        Br(builder,whilecondblock);

        IR_Atend(builder,whilecondblock);
        currentBlock = whilecondblock;
        currentBlockName = "while_bb";
        IR_BaseBlock whilebody = IR_BaseBlock.add_Baseblock(currentFunction,"while_body",currentScope.getDep());
        IR_BaseBlock whileentry = IR_BaseBlock.add_Baseblock(currentFunction,"while_entry",currentScope.getDep());
        trueblock = whilebody;
        falseblock = whileentry;
        IR_Value whilecond = visit(ctx.cond());
        if(i32Type.equals(whilecond.get_Type())){
            // i32 类型转 i1
            whilecond = Icmp(builder,whilecond,i32zero,IR_NE,"ne_tmp");
        }
        if(whilecond instanceof IR_Float_Value){
            whilecond = Icmp(builder,whilecond,i32zero,IR_NE,"ne_tmp");
        }
        Cond(builder,whilecond,whilebody,whileentry);
        //tmepcurrentbb  = cond;
        //IR_BaseBlock tmepcurrentbb = getbuilderbb(builder);
        IR_Atend(builder,whileentry);
        setbuilderbb(builder, currentBlock);
        IR_Atend(builder,whilebody);

        //setbuilderbb(builder, whilebody);

        currentBlock = whilebody;
        currentBlock.add_nextList(whileentry);
        currentBlockName = "whilebody";
        //在下面这一步访问 block里面的时候将 scope的名字进行了修改
        visit(ctx.stmt());
        Br(builder,whilecondblock);

        IR_Atend(builder,whilecondblock);
        setbuilderbb(builder, whileentry);
        currentBlock = whileentry;
        isbreak = false;
        iscontinue = false;
        trueblock = null;
        falseblock = null;
        return null;
    }

    public IR_Value visitContinue(SysYParser.ContinueContext ctx) {
        //找到最近的一个while块
        IR_BaseBlock whilebb = currentScope.findwhile();
        IR_BaseBlock whilecond = (IR_BaseBlock) whilebb.get_preList().get(0);

        IR_BaseBlock tmpcurrentbb = getbuilderbb(builder);
        Br(builder,whilecond);
        //currentBlock.get_nextList().clear();
        currentBlock.getNextBlock().clear();
        IR_Atend(builder,whilecond);

        setbuilderbb(builder, tmpcurrentbb);
        iscontinue = true;
        return null;
    }

    public IR_Value visitBreak(SysYParser.BreakContext ctx) {
        IR_BaseBlock whilebb = currentScope.findwhile();
        IR_BaseBlock whileentry = (IR_BaseBlock) whilebb.get_nextList().get(0);

        IR_BaseBlock tmpcurrentbb = getbuilderbb(builder);
        Br(builder,whileentry);
        //currentBlock.get_nextList().clear();
        currentBlock.getNextBlock().clear();
        IR_Atend(builder,whileentry);
        setbuilderbb(builder, tmpcurrentbb);
        isbreak = true;
        return null;
    }

    public void test_IR_Opt_Code() {
        // 打印优化后的ir
        System.out.println("Instructions:");
        for (IR_FuncBlock function : this.module.getFuncBlocks()) {
            for (IR_BaseBlock block : function.get_bb_List()) {
                System.out.println("Block: " + block.get_ValueName());
                List<Instruction> instructions = block.get_Instruction_List();
                for (Instruction instruction : instructions) {
                    System.out.println(instruction);
                }
                System.out.println();
            }
        }
        System.out.println();
    }

    public IR_Builder getBuilder(){
        return this.builder;
    }
}
